package com.tanhua.server.service;
import com.tanhua.domain.mongo.FollowUser;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.VideoVo;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.VideoApi;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class VideoService {

    @Reference
    private VideoApi videoApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private FastFileStorageClient storageClient;
    @Autowired
    private FdfsWebServer fdfsWebServer;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private VideoMqService videoMqService;

    /**
     * 接口名称：小视频列表
     */
    @Cacheable(value = "videolist_",key = "#page + '_' + #pagesize")
    public PageResult videoList(Integer page, Integer pagesize) {
        log.info("查询小视频列表，读取数据库：");
        //1. 分页查询小视频列表
        // 【修改查询：首先从redis查询，没有查询到推荐系统推荐的数据，再查询mongo】
        PageResult pageResult = findByRecommend(page,pagesize);
        if (pageResult == null){
            pageResult = videoApi.findByPage(page, pagesize);
        }
        //2. 获取小视频集合
        List<Video> videoList = (List<Video>) pageResult.getItems();
        //3. 封装vo
        List<VideoVo> voList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(videoList)) {
            for (Video video : videoList) {
                //3.1 创建vo、封装vo
                VideoVo vo = new VideoVo();
                vo.setId(video.getId().toString());

                // 根据用户id查询
                UserInfo userInfo =
                        userInfoApi.findById(video.getUserId());
                if (userInfo != null) {
                    BeanUtils.copyProperties(userInfo,vo);
                }
                // 封装vo: video--->vo
                BeanUtils.copyProperties(video,vo);
                // 封装vo的其他属性（没有与Video对应上的）
                vo.setCover(video.getPicUrl());
                vo.setSignature(video.getText());

                String key = "followUser_"+UserHolder.getUserId()+"_"+video.getUserId();
                if (redisTemplate.hasKey(key)) {
                    vo.setHasFocus(1);
                } else {
                    vo.setHasFocus(0);
                }
                vo.setHasLiked(0);

                //3.2 添加到集合
                voList.add(vo);
            }
        }
        //4. 把封装好的vo集合设置到分页对象中、返回
        pageResult.setItems(voList);
        return pageResult;
    }

    // 查询redis中推荐视频记录
    private PageResult findByRecommend(Integer page, Integer pagesize) {
        //1. 拼接redis中的key
        String key = "QUANZI_VIDEO_RECOMMEND_" + UserHolder.getUserId();
        //2. 根据key获取推荐用户:  18,20,20,22,4,10,23,25,24,10
        String value = redisTemplate.opsForValue().get(key);
        //3. 判断
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        //4. 分割字符串  18,20,20,22,4,10,23,25,24,10
        String[] pids = value.split(",");
        int counts = pids.length;
        // 查询的起始
        int startIndex = (page - 1) * pagesize;
        if(startIndex < pids.length) { //起始条数小于数据总数
            int endIndex = startIndex + pagesize - 1;
            if (endIndex >= pids.length) {
                endIndex = pids.length - 1;
            }
            List<Long> vidList = new ArrayList<>();   //本页查询的所有动态的pid列表
            for (int i = startIndex; i <= endIndex; i++) {
                vidList.add(Long.valueOf(pids[i]));
            }
            //本次分页的数据列表
            List<Video> list = videoApi.findByPids(vidList);
            return new PageResult(page, pagesize, counts, list);
        }
        return null;
    }

    /**
     * 接口名称：视频上传
     * @param videoThumbnail 封面图片，上传到阿里云OSS
     * @param videoFile 视频上传到fastdfs
     * @return
     */
    @CacheEvict(value = "videolist_",allEntries = true)
    public ResponseEntity<Object> saveVideo(String text,
            MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        //1. 上传封面图片
        String picUrl = ossTemplate.upload(
                videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());

        //2. 上传小视频到fastdfs上
        //2.1 获取文件名
        String fileName = videoFile.getOriginalFilename();
        //2.2 获取后缀
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        //2.3 上传
        StorePath storePath = storageClient.uploadFile(videoFile.getInputStream(), videoFile.getSize(), suffix, null);
        //2.4 获取完整的weburl访问地址
        String videoUrl = fdfsWebServer.getWebServerUrl()+storePath.getFullPath();

        //3. 创建video对象并保存
        Video video = new Video();
        // 设置主键
        video.setId(ObjectId.get());
        video.setCreated(System.currentTimeMillis());
        video.setUserId(UserHolder.getUserId());
        video.setText(text==null||"".equals(text) ? "左手右手一个慢动作" : text);
        video.setPicUrl(picUrl);
        video.setVideoUrl(videoUrl);

        videoApi.save(video);

        try {
            // 发送mq消息
            videoMqService.videoMsg(video.getId().toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：视频用户关注
     */
    public ResponseEntity<Object> userFocus(Long followUserId) {
        // 获取登陆用户id
        Long userId = UserHolder.getUserId();
        // 创建视频用户关注的对象
        FollowUser followUser = new FollowUser();
        followUser.setCreated(System.currentTimeMillis());
        followUser.setUserId(userId);
        followUser.setFollowUserId(followUserId);

        // 保存关注的数据
        videoApi.followUser(followUser);

        // 记录关注的标记
        String key = "followUser_"+userId+"_"+followUserId;
        redisTemplate.opsForValue().set(key,"1");

        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：视频用户关注 - 取消
     * @param unfollowUserId 取消关注的用户
     * @return
     */
    public ResponseEntity<Object> userUnFocus(Long unfollowUserId) {
        // 1.获取用户id
        Long userId = UserHolder.getUserId();
        // 2.删除follow_user表的数据
        //db.follow_user.remove({userId:登陆用户,followUserId:取消关注的用户})
        videoApi.userUnFocus(userId,unfollowUserId);
        // 3. 删除redis中的关注的标记
        String key = "followUser_"+userId+"_"+unfollowUserId;
        redisTemplate.delete(key);
        return ResponseEntity.ok(null);
    }
}
